import { isClient, toRef, tryOnScopeDispose, useEventListener } from '@vueuse/core'

//vueuse的事件订阅中没有传递lastEventId出来
function resolveNestedOptions$1(options) {
    if (options === true)
        return {}
    return options
}

export default (url, events = [], options = {}) => {
    const event = ref(null);
    const data = ref(null);
    const status = ref("CONNECTING");
    const eventSource = ref(null);
    const error = shallowRef(null);
    const urlRef = toRef(url);
    const lastEventId = shallowRef(null);
    let explicitlyClosed = false;
    let retried = 0;
    const {
        withCredentials = false,
        immediate = true
    } = options;
    const close = () => {
        if (isClient && eventSource.value) {
            eventSource.value.close();
            eventSource.value = null;
            status.value = "CLOSED";
            explicitlyClosed = true;
        }
    };
    const _init = () => {
        if (explicitlyClosed || typeof urlRef.value === "undefined")
            return;
        const es = new EventSource(urlRef.value, { withCredentials });
        status.value = "CONNECTING";
        eventSource.value = es;
        es.onopen = () => {
            status.value = "OPEN";
            error.value = null;
        };
        es.onerror = (e) => {
            status.value = "CLOSED";
            error.value = e;
            if (es.readyState === 2 && !explicitlyClosed && options.autoReconnect) {
                es.close();
                const {
                    retries = -1,
                    delay = 1e3,
                    onFailed
                } = resolveNestedOptions$1(options.autoReconnect);
                retried += 1;
                if (typeof retries === "number" && (retries < 0 || retried < retries))
                    setTimeout(_init, delay);
                else if (typeof retries === "function" && retries())
                    setTimeout(_init, delay);
                else
                    onFailed == null ? void 0 : onFailed();
            }
        };
        es.onmessage = (e) => {
            event.value = null;
            data.value = e.data;
            lastEventId.value = e.lastEventId;
        };
        for (const event_name of events) {
            useEventListener(es, event_name, (e) => {
                event.value = event_name;
                data.value = e.data || null
                lastEventId.value = e.lastEventId
            });
        }
    };
    const open = () => {
        if (!isClient)
            return;
        close();
        explicitlyClosed = false;
        retried = 0;
        _init();
    };
    if (immediate)
        watch(urlRef, open, { immediate: true });
    tryOnScopeDispose(close);
    return {
        eventSource,
        event,
        data,
        status,
        error,
        open,
        close,
        lastEventId
    };
}
